/*
 * Copyright (C) 2012 Jakub Narloch (jmnarloch@gmail.com), All Rights Reserved.
 */

package org.soa.security.service.impl;

import org.soa.security.dao.KeyStoreDAO;
import org.soa.security.dao.LookupDAO;
import org.soa.security.dao.SoaDAOException;
import org.soa.security.model.entities.DataSourceType;
import org.soa.security.model.entities.LookupEntity;
import org.soa.security.model.entities.SecurityType;
import org.soa.security.model.entities.ServiceType;
import org.soa.security.model.entities.UserRole;
import org.soa.security.service.LookupService;
import org.soa.security.service.SoaServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 *
 */
@Service
@Transactional(readOnly = true)
public class LookupServiceImpl implements LookupService {

    /**
     * <p>Instance of {@link LookupDAO} used for retrieving lookup entities.</p>
     *
     * <p>Null by default.</p>
     *
     * <p>Autowired by IOC container.</p>
     */
    @Autowired
    private LookupDAO lookupDAO;

    /**
     * <p>Creates new instance of {@link LookupServiceImpl} class.</p>
     */
    public LookupServiceImpl() {
        // empty constructor
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<UserRole> getUserRoles() throws SoaServiceException {

        try {
            return getLookupEntities(lookupDAO.getUserRoles(), UserRole.class);
        } catch (SoaDAOException e) {
            throw new SoaServiceException("Exception occurred when retrieving user roles.", e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<ServiceType> getServiceTypes() throws SoaServiceException {

        try {
            return getLookupEntities(lookupDAO.getServiceTypes(), ServiceType.class);
        } catch (SoaDAOException e) {
            throw new SoaServiceException("Exception occurred when retrieving service types.", e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<DataSourceType> getDataSourceTypes() throws SoaServiceException {

        try {
            return getLookupEntities(lookupDAO.getDataSourceTypes(), DataSourceType.class);
        } catch (SoaDAOException e) {
            throw new SoaServiceException("Exception occurred when retrieving data source types.", e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<SecurityType> getSecurityTypes() throws SoaServiceException {

        try {
            return getLookupEntities(lookupDAO.getSecurityTypes(), SecurityType.class);
        } catch (SoaDAOException e) {
            throw new SoaServiceException("Exception occurred when retrieving security types.", e);
        }
    }

    /**
     * @param lookupEntities
     * @param entityClass
     * @param <T>
     *
     * @return
     *
     * @throws SoaServiceException
     */
    private <T extends LookupEntity> List<T> getLookupEntities(List<T> lookupEntities, Class<T> entityClass) throws SoaServiceException {

        ArrayList<T> result = new ArrayList<>();

        T defaultElement = createNewInstance(entityClass);
        defaultElement.setId(0);
        defaultElement.setName("-- Select --");
        result.add(defaultElement);
        result.addAll(lookupEntities);

        return result;
    }

    /**
     * @param entityClass
     * @param <T>
     * @param <T>
     *
     * @return
     */
    private <T extends LookupEntity> T createNewInstance(Class<T> entityClass) throws SoaServiceException {

        try {
            return entityClass.newInstance();
        } catch (InstantiationException e) {
            throw new SoaServiceException("Error occured when creating object instance.", e);
        } catch (IllegalAccessException e) {
            throw new SoaServiceException("Error occured when creating object instance.", e);
        }
    }
}
